#pragma once
#ifndef _ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_
#define _ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_

#include "physfs/physfs.h"
#include "core/core_utils.h"
#include "Log/LogSystem.h"
#include <string>
#include <vector>
#include <boost/filesystem.hpp>

namespace z3d{
	namespace utils{
		/*! \brief This class represents a virtual file system. With this class you gain the ability to put your files in a 7z file.
		*
		* The CVirtualFileSystem class is a wrapper for icculus physfs system. You can use this class to extract (deploy) your files form a compressed 
		* file. The class use a manager in order to keep track of the deployed files. 
		* A simple example:
		* <b>[Init VFS]</b>
		* <code>
		* zel::utils::CVirtualFileSystem vfs;
		* vfs.init();
		* // Here you insert the root path where your resources must be found
		* vfs.setSystemResourcesBasePath(path);
		* // Here you configure a root path where you'll write your deployed files. This directory must be inside the directory you set
		* // in <i>vfs.setSystemResourcesBasePath</i>
		* vfs.setWriteDirectory(path)
		* <br>
		* <b>[Add resources to be searched for]</b>
		* // add locations where you put your resources in the order in wich you'll search. 
		* // If a file with the same name is into location 2 and 3, then the first one will be choosen. This could be a good mechanism to add mods
		* vfs.addLocationToSearch(files_location_1, 1);
		* vfs.addLocationToSearch(files_location_2, 2);
		* vfs.addLocationToSearch(files_location_3, 3);
		* </code>
		* After that you can check if a file exists, deploy files or load directly into memory. 
		*/
		class CVirtualFileSystem
		{	
			/// where to find zip resources that  belonging to the system
			std::string m_systemResourcesBasePath;
			std::string m_writingAllowedPath;
			/// @summary	The log system
			glog::CGlobalLog* m_log;
			/// @summary	The appender
			const std::string VFS_APPENDER;
			bool m_isInitialized;
			z3d::core::cuManager<const char*, const char *> m_deployedManager;
		protected:
			uint32_t pathCreator(const boost::filesystem::path& path_to_create );
		public:
			enum DEPLOY_MODE{
				DPMOD_NORMAL,
				DPMOD_SHADOW,
				DPMOD_SHADOW_WITH_EXTENSION
			};
			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void setSystemResourcesBasePath(const char* path)
			///
			/// \brief	Sets a system resources base path. 
			///
			/// \author	Ferran Ferri
			/// \date	16/06/2011
			///
			/// \param [in,out]	path	If non-null, pathname. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			void setSystemResourcesBasePath(const char* path);

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	std::string getSystemResourcesBasePath()
			///
			/// \brief	Gets the system resources base path. 
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \return	The system resources base path. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			std::string getSystemResourcesBasePath(){return m_systemResourcesBasePath;}

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	int init()
			///
			/// \brief	Initialises this object. 
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \return	. 
			////////////////////////////////////////////////////////////////////////////////////////////////////

			int init();

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	int addLocationToSearch(const char* location, int order)
			///
			/// \brief	Adds a location to search with order 'order'
			///
			/// \author	Ferran Ferri
			/// \date	23/06/2011
			///
			/// \param [in,out]	location	If non-null, the location you want to insert. 
			/// \param	order				The order in wich locations are explorer, starting by 0. 
			///
			/// \return	ZEL_ERROR_NO_ERROR if not problem found
			////////////////////////////////////////////////////////////////////////////////////////////////////

			int addLocationToSearch(const char* location, int order);
			int setWriteDirectory(const char* location);
			bool checkIfFileExists(const char* fileName);
			char* loadFileIntoMemory(const char* fileName);
			const char* deployFile(const char* fileName,DEPLOY_MODE mode);
			void deleteFile(const char* fileName);
			void deleteDeployedFiles();

			////////////////////////////////////////////////////////////////////////////////////////////////////
			/// \fn	void reset()
			///
			/// \brief	resets the class without destroying it, letting the user to re-init (calling init method)
			///
			/// Calling reset, the user deletes all information about wrtie directory path, resources location and base resource location.
			/// Also, all deployed files names are removed of the manager. <b>Note that no files deployed on the hard disk are deleted</b>, so deployed files
			/// remain untouched into the write directory. To delete deployed files, call the corresponding method.
			///
			/// \author	Ferran Ferri
			/// \date	29/06/2011
			///
			////////////////////////////////////////////////////////////////////////////////////////////////////

			void reset();
			CVirtualFileSystem(void);
			~CVirtualFileSystem(void);
		};
	};
};
#endif //_ZELESTE_ZEL_UTILS_VIRTUALFILESYSTEM_H_